package com.df.my_net_game.net.tcp;


import com.df.my_net_game.game_rpc.GRpcHeader;
import com.df.my_net_game.game_rpc.EzGameMsg;
import com.df.my_net_game.net.base.EzGameMsgDispatcher;
import com.df.my_net_game.net.base.GTcpServer;
import com.df.my_net_game.net.base.IServerCB;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.ByteToMessageCodec;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetSocketAddress;
import java.util.List;

/**
 * @author Admin
 * @class MsgAdapter
 * @date 2024/4/3 15:49
 */
public class EzGameTcpDefaultMsgHandler extends ByteToMessageCodec<EzGameMsg> {

	/**
	 * 日志
	 */
	Logger log = LoggerFactory.getLogger(EzGameTcpDefaultMsgHandler.class);
	IServerCB iServerCB;

	GTcpServer server;


	public EzGameTcpDefaultMsgHandler(GTcpServer server) {
		this.iServerCB = server.getServerCB();
		this.server = server;
	}


	/***
	 * 数据处理
	 * 
	 * @author: Admin
	 * @date: 2024/4/3 15:49
	 * @param ctx
	 *            channel上下文
	 *            数据
	 * @return: void
	 */
//	@Override
//	protected void channelRead0(ChannelHandlerContext ctx, ByteBuf byteBuf) throws Exception {
//		try {
//			//TODO 参考dubbo 的协议格式
//			//魔数 2字节
//			//请求还是响应 (1bit) 0请求 1响应
//			//
//			//协议格式：
//			//魔数+消息总长度+header+body
//			//魔数+cmdId+消息总长度+header+body
//			//TODO 魔数处理
//			if(byteBuf.readableBytes()<4){
//				return;
//			}
//			byteBuf.markReaderIndex();
//			int allMsgLen = byteBuf.readInt();
//			if(byteBuf.readableBytes() < allMsgLen-4){
//				byteBuf.resetReaderIndex();
//				return;
//			}
//			//todo 循环读一个消息长度进行解析
//			EzGameMsg msg = new EzGameMsg();
//			msg.setChannel(ctx.channel());
//
//			GRpcHeader header = new GRpcHeader();
//			int headerLen = byteBuf.readInt();
//			msg.setHeader(header);
//			byte[] headerBytes = new byte[headerLen-4];
//			byteBuf.readBytes(headerBytes);
//			header.readFromBytes(headerBytes);
//			if(header.getReqFrom().equals(0)){//消息来自客户端 TODO 消息转发的时候这个填多少呢
//				InetSocketAddress socketAddress = (InetSocketAddress) ctx.channel().remoteAddress();
//				String hostAddress = socketAddress.getAddress().getHostAddress();
//				header.addHeader("clientAdress",hostAddress);
//				header.addHeader("clientPort",socketAddress.getPort()+"");
//			}
//			int bodyLen = allMsgLen-4-headerLen;
//			if(bodyLen>0){
//				byte[] bodyBytes = new byte[bodyLen];
//				byteBuf.readBytes(bodyBytes);
//				msg.setBodyBytes(bodyBytes);
//			}
//			//TODO 缓存消息？
//			//TODO 消息唯一id 检测
//
//			if(iServerCB!=null){
//				msg = iServerCB.onReceiveMsg(msg,server);
//			}
//			if(msg==null){
//				return;
//			}
//			//TODO 如果是请求检测是否路由到其他机器
//			//不路由，则分发到本地机器执行
//			EzGameMsgDispatcher.getInstance().dispatcherMsg(msg,ctx);
//
//			//TODO 如果是响应则返回给请求方
//
//			//检测消息类型，如果是请求，则分发，如果是响应，
//		} catch (Exception e) {
//			e.printStackTrace();
//		}
//	}




	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
		super.channelActive(ctx);
//		InetSocketAddress socketAddress = (InetSocketAddress) ctx.channel().remoteAddress();
//		String hostAddress = socketAddress.getAddress().getHostAddress();
//		Integer port = socketAddress.getPort();
//		log.info("Channel Active:  "+hostAddress+":"+port);
		try {
			if(iServerCB!=null){
				iServerCB.onConnected(ctx,server);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
		cause.printStackTrace();
		try {
			if(iServerCB!=null){
				iServerCB.onException(ctx,cause,server);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
//		ctx.channel().writeAndFlush(new CloseWebSocketFrame());
//		ctx.close();
		super.exceptionCaught(ctx, cause);
	}

	/***
	 * 断开连接时触发 新建连接 -> handlerAdded -> channelRegistered -> channelActive ->
	 * channelRead | \/ 关闭连接 <- handlerRemoved <- channelUnregistered <-
	 * channelInactive <- channelReadComplete
	 * 
	 * @author: Admin
	 * @date: 2024/4/7 18:01
	 * @param ctx
	 *            Channel上下文
	 * @return: void
	 */
	@Override
	public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
		try {
			if(iServerCB!=null){
				iServerCB.onDisconnected(ctx,server);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	protected void encode(ChannelHandlerContext ctx, EzGameMsg ezGameMsg, ByteBuf byteBuf) throws Exception {
		try {
			int len = 4;
			byte[] headerBytes = ezGameMsg.getHeader().tobytes();
			len+=headerBytes.length;
			byte[] bodyBytes = ezGameMsg.toBodyBytes();
			if(bodyBytes!=null){
				len+=bodyBytes.length;
			}
			byteBuf.writeInt(len);
			byteBuf.writeBytes(headerBytes);
			if(bodyBytes!=null){
				byteBuf.writeBytes(bodyBytes);
			}
		}catch (Exception e){
			e.printStackTrace();
		}
	}

	@Override
	protected void decode(ChannelHandlerContext ctx, ByteBuf byteBuf, List<Object> list) throws Exception {
		try {
			//TODO 参考dubbo 的协议格式
			//魔数 2字节
			//请求还是响应 (1bit) 0请求 1响应
			//
			//协议格式：
			//魔数+消息总长度+header+body
			//魔数+cmdId+消息总长度+header+body
			//TODO 魔数处理
			if(byteBuf.readableBytes()<4){
				return;
			}
			byteBuf.markReaderIndex();
			int allMsgLen = byteBuf.readInt();
			if(byteBuf.readableBytes() < allMsgLen-4){
				byteBuf.resetReaderIndex();
				return;
			}
			//todo 循环读一个消息长度进行解析
			EzGameMsg msg = new EzGameMsg();
			msg.setChannel(ctx.channel());

			GRpcHeader header = new GRpcHeader();
			int headerLen = byteBuf.readInt();
			msg.setHeader(header);
			byte[] headerBytes = new byte[headerLen-4];
			byteBuf.readBytes(headerBytes);
			header.readFromBytes(headerBytes);
			if(header.getReqFrom().equals(0)){//消息来自客户端 TODO 消息转发的时候这个填多少呢
				InetSocketAddress socketAddress = (InetSocketAddress) ctx.channel().remoteAddress();
				String hostAddress = socketAddress.getAddress().getHostAddress();
				header.addHeader("clientAdress",hostAddress);
				header.addHeader("clientPort",socketAddress.getPort()+"");
			}
			int bodyLen = allMsgLen-4-headerLen;
			if(bodyLen>0){
				byte[] bodyBytes = new byte[bodyLen];
				byteBuf.readBytes(bodyBytes);
				msg.setBodyBytes(bodyBytes);
			}
			//TODO 缓存消息？
			//TODO 消息唯一id 检测

			if(iServerCB!=null){
				msg = iServerCB.onReceiveMsg(msg,server);
			}
			if(msg==null){
				return;
			}
			//TODO 消息模式：请求不响应；请求响应；服务器广播
			//TODO 如果是请求检测是否路由到其他机器
			//不路由，则分发到本地机器执行
			EzGameMsgDispatcher.getInstance().dispatcherMsg(msg,ctx);

			//TODO 如果是响应则返回给请求方

			//检测消息类型，如果是请求，则分发，如果是响应，
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
